package main

import "fmt"

func main() {
	// 定义一个 int 切片
	var s1 []int
	// 定义并初始化切片
	var s2 = []int{1, 2, 3}

	fmt.Printf("s1: %T %+v\n", s1, s1)
	fmt.Printf("s2: %T %+v\n", s2, s2)

	fmt.Println("=========================================================")

	// 未初始化时为 nil
	fmt.Printf("s1 == nil : %t\n", s1 == nil)
	fmt.Printf("s2 == nil : %t\n", s2 == nil)

	fmt.Println("=========================================================")

	// 长度和容量
	fmt.Printf("s1 长度: %d, 容量: %d\n", len(s1), cap(s1))
	fmt.Printf("s2 长度: %d, 容量: %d\n", len(s2), cap(s2))

	fmt.Println("=========================================================")

	// 从数组获取切片
	a1 := [...]int{0, 1, 2, 3, 4, 5}
	fmt.Printf("a1: %T %+v\n", a1, a1)
	// 基于数组进行切割
	// 数组[起始下标:截止下标]
	// 从起始下标开始 到截止下标为止(不包含) 左闭右开
	// 切片的容量是指底层数组的容量
	// 切片容量的大小是 从 切片的第一个元素下标 到 被切割的数组/切片最后一个元素下标 的长度
	s3 := a1[1:4]
	fmt.Printf("s3: %T %+v\n", s3, s3)
	fmt.Printf("s3 长度: %d, 容量: %d\n", len(s3), cap(s3))

	// a1[:4] => a1[0:4]
	s4 := a1[:4]
	fmt.Printf("s4: %T %+v\n", s4, s4)
	fmt.Printf("s4 长度: %d, 容量: %d\n", len(s4), cap(s4))

	// a1[4:] => a1[4:最后一个下标] => a1[4:len(a1)]
	s5 := a1[4:]
	fmt.Printf("s5: %T %+v\n", s5, s5)
	fmt.Printf("s5 长度: %d, 容量: %d\n", len(s5), cap(s5))

	// a1[4:] => a1[4:最后一个下标] => a1[4:len(a1)]
	s6 := s5[1:]
	fmt.Printf("s6: %T %+v\n", s6, s6)
	fmt.Printf("s6 长度: %d, 容量: %d\n", len(s6), cap(s6))

	fmt.Println("=========================================================")

	// 切片 是引用类型 内部都指向底层的同一个数组
	fmt.Printf("a1: %T %+v    ", a1, a1)
	fmt.Printf("s5: %T %+v    ", s5, s5)
	fmt.Printf("s6: %T %+v\n", s6, s6)

	// 修改底层数组的值
	a1[len(a1)-1] = 666

	fmt.Printf("a1: %T %+v    ", a1, a1)
	fmt.Printf("s5: %T %+v    ", s5, s5)
	fmt.Printf("s6: %T %+v\n", s6, s6)

	fmt.Println("=========================================================")

	// 使用 make 创建切片
	//  make([]类型,长度,容量) 容量不填时 默认 与 长度相同
	s7 := make([]int, 5, 10)
	fmt.Printf("s7: %T %+v\n", s7, s7)
	fmt.Printf("s7 长度: %d, 容量: %d\n", len(s7), cap(s7))

	s8 := make([]int, 0, 10)
	fmt.Printf("s8: %T %+v\n", s8, s8)
	fmt.Printf("s8 长度: %d, 容量: %d\n", len(s8), cap(s8))

	fmt.Println("=========================================================")

	// 切片 为引用类型 会被修改
	s9 := []bool{true, true, true}
	s10 := s9

	fmt.Printf("s9: %T %+v\n", s9, s9)
	fmt.Printf("s10: %T %+v\n", s10, s10)

	s10[1] = false

	fmt.Printf("s9: %T %+v\n", s9, s9)
	fmt.Printf("s10: %T %+v\n", s10, s10)

	fmt.Println("=========================================================")

	// 切片遍历
	// for...i 循环时需使用 len() 而不能使用 cap()
	for i := 0; i < len(s10); i++ {
		fmt.Printf("%d, %v   ", i, s10[i])
	}

	fmt.Println()

	for i, v := range s10 {
		fmt.Printf("%d, %v   ", i, v)
	}
}
